﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.ServiceModel.Channels;
using System.Runtime.InteropServices;
using LogLib;
using System.IO;
using System.Drawing.Imaging;

namespace ComLib.ComFun
{
    public class BufferManage : IDisposable
    {
        private static BufferManage _instance;

        private static readonly Object syncLock = new Object();

        public static void CreatInstance()
        {
            BufferManage._instance = new BufferManage();
        }

        public static void ReleaseInstance()
        {
            if (BufferManage._instance != null)
            {
                BufferManage._instance.Dispose();
            }
        }

        public static BufferManage Instance
        {
            get
            {
                return BufferManage._instance;
            }
        }

        /// <summary>
        /// 错误信息
        /// </summary>
        private string _errorMessage = "";
        public string ErrorMessage
        {
            get { return _errorMessage; }
            set { _errorMessage = value; }
        }

        private const int UnitBufferSize = 1024576;

        private BufferManager _bufferPool = null;

        private void ClearArray(byte[] dataArr)
        {
            Array.Clear(dataArr, 0, dataArr.Length);
        }

        public bool CreatPool(int maxSize)
        {
            _errorMessage = "";
            try
            {
                _bufferPool = BufferManager.CreateBufferManager(maxSize * UnitBufferSize * 4, maxSize * UnitBufferSize);
                return true;
            }
            catch (Exception ex)
            {
                _errorMessage = ex.Message;
                Log.WriteException(ex.ToString());
                return false;
            }
        }

        public byte[] TakeBuffer(int length)
        {
            return _bufferPool.TakeBuffer(length);
        }

        public void ReturnBuffer(byte[] array)
        {
            _bufferPool.ReturnBuffer(array);
        }

        /// <summary>  
        /// 获取bitmap的JPEG格式的byte数据，并输出stride  
        /// </summary>  
        /// <param name="bmp"></param>  
        /// <param name="stride"></param>  
        /// <returns></returns>  
        public byte[] GetJPEGValues(Bitmap bmp, out int bufferLength)
        {
            bufferLength = 0;
            _errorMessage = "";
            byte[] buffer = null;
            try
            {
                using (MemoryStream stream = new MemoryStream())
                {
                    bmp.Save(stream, ImageFormat.Jpeg);
                    bufferLength = Convert.ToInt32(stream.Length);
                    buffer = _bufferPool.TakeBuffer(bufferLength);
                    stream.Seek(0, SeekOrigin.Begin);
                    stream.Read(buffer, 0, bufferLength);                   
                    stream.Close();
                    stream.Dispose();     
                }
                return buffer;
            }
            catch(Exception ex)
            {
                _errorMessage = ex.Message;
                Log.WriteException(ex.ToString());
                return null;
            }
        }

        public byte[] GetFileByteArray(string strFilePath, out long length)
        {
            length = 0;
            byte[] buffer = null;
            try
            {
                using (FileStream stream = new FileInfo(strFilePath).OpenRead())
                {
                    int len = Convert.ToInt32(stream.Length);
                    buffer = _bufferPool.TakeBuffer(len);
                    stream.Seek(0, SeekOrigin.Begin);
                    stream.Read(buffer, 0, len);
                    stream.Close();
                    stream.Dispose();
                }
                return buffer;
            }
            catch (Exception ex)
            {
                _errorMessage = ex.Message;
                Log.WriteException(ex.ToString());
                return null;
            }
        }

        public byte[] GetJPEGByteArray(string strFilePath)
        {
            int length = 0;
            byte[] buffer = null;
            try
            {
                using (FileStream stream = new FileInfo(strFilePath).OpenRead())
                {
                    length = Convert.ToInt32(stream.Length);
                    buffer = _bufferPool.TakeBuffer(length);
                    stream.Seek(0, SeekOrigin.Begin);
                    stream.Read(buffer, 0, length);                  
                    stream.Close();
                    stream.Dispose();                   
                }
                return buffer;
            }
            catch (Exception ex)
            {
                _errorMessage = ex.Message;
                Log.WriteException(ex.ToString());
                return null;
            }           
        }

        /// <summary>  
        /// 获取bitmap的BMP格式的byte数据，并输出stride  
        /// </summary>  
        /// <param name="bmp"></param>  
        /// <param name="stride"></param>  
        /// <returns></returns>  
        public byte[] GetBMPValues(Bitmap bmp, out int length)
        {
            _errorMessage = "";
            length = 0;
            byte[] buffer = null;
            try
            {
                using (MemoryStream stream = new MemoryStream())
                {
                    bmp.Save(stream, ImageFormat.Bmp);
                    length = Convert.ToInt32(stream.Length);
                    buffer = _bufferPool.TakeBuffer(length);
                    stream.Seek(0, SeekOrigin.Begin);
                    stream.Read(buffer, 0, length);                  
                    stream.Close();
                    stream.Dispose();
                }
                return buffer;
            }
            catch (Exception ex)
            {
                _errorMessage = ex.Message;
                Log.WriteException(ex.ToString());
                return null;
            }
        }

        /// <summary>  
        /// 获取bitmap的byte数据，并输出stride  
        /// </summary>  
        /// <param name="bmp"></param>  
        /// <param name="stride"></param>  
        /// <returns></returns>  
        public byte[] GetBGRValues(Bitmap bmp, out int length)
        {
            length = 0;
            _errorMessage = "";
            try
            {               
                var rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
                var bmpData = bmp.LockBits(rect, 
                    System.Drawing.Imaging.ImageLockMode.ReadOnly,
                    PixelFormat.Format24bppRgb);
                int stride = bmpData.Stride;
                var rowBytes = bmpData.Width * Image.GetPixelFormatSize(PixelFormat.Format24bppRgb) / 8;
                length = bmp.Height * rowBytes;
                byte[] buffer = _bufferPool.TakeBuffer(length);
                IntPtr ptr = bmpData.Scan0;
                for (var i = 0; i < bmp.Height; i++)
                {
                    Marshal.Copy(ptr, buffer, i * rowBytes, rowBytes);   //对齐  
                    ptr += bmpData.Stride; // next row  
                }
                bmp.UnlockBits(bmpData);
                return buffer;
            }
            catch (Exception ex)
            {
                _errorMessage = ex.Message;
                Log.WriteException(ex.ToString());
                return null;
            }
        }

        public void Dispose()
        {
            if (_bufferPool != null)
            {
                _bufferPool.Clear();
            }
        }
    }
}
